"""
Word 格式导出策略
生成包含参数表格的Word文档
"""
from __future__ import annotations

from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List

from docx import Document
from docx.shared import Inches, Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.shared import OxmlElement, qn
from docx.oxml.ns import qn as nsqn

from ..domain import ProjectSnapshot
from .base import ExportStrategy, ExportResult


class WordExportStrategy(ExportStrategy):
    """将项目快照导出为 Word 文件"""

    @classmethod
    def get_format_info(cls) -> Dict[str, Any]:
        """获取 Word 导出格式信息"""
        return {
            "format": "word",
            "name": "Word文档",
            "extension": ".docx",
            "description": "包含参数表格的Word文档，适用于报告附件"
        }

    def __init__(self, output_dir: Path = Path("exports")) -> None:
        self.output_dir = output_dir
        # 字体设置：小5字体，中文宋体，英文Times New Roman
        self.font_size = Pt(9)  # 小5字体约为9pt
        self.chinese_font = "宋体"
        self.english_font = "Times New Roman"

    def export(self, snapshot: ProjectSnapshot) -> ExportResult:
        snapshot.ensure_export_time()
        self.output_dir.mkdir(parents=True, exist_ok=True)
        timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
        filename = f"{snapshot.metadata.name_en}_parameters_{timestamp}.docx"
        file_path = self.output_dir / filename

        # 创建Word文档
        doc = Document()

        # 设置文档标题
        self._add_document_title(doc, snapshot)

        # 添加三个参数表格
        self._add_single_value_table(doc, snapshot)
        self._add_year_list_table(doc, snapshot)
        self._add_noyear_list_table(doc, snapshot)

        # 保存文档
        doc.save(file_path)

        return ExportResult(
            file_path=file_path,
            mime_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        )

    def get_diff_ignore_fields(self) -> List[str]:
        return []

    def _set_font_for_run(self, run, text: str):
        """为文本run设置字体：中文用宋体，英文用Times New Roman"""
        run.font.size = self.font_size

        # 检查文本是否包含中文字符
        has_chinese = any('\u4e00' <= char <= '\u9fff' for char in text)

        if has_chinese:
            # 包含中文，使用宋体
            run.font.name = self.chinese_font
            run._element.rPr.rFonts.set(nsqn('w:eastAsia'), self.chinese_font)
        else:
            # 纯英文，使用Times New Roman
            run.font.name = self.english_font
            run._element.rPr.rFonts.set(nsqn('w:ascii'), self.english_font)
            run._element.rPr.rFonts.set(nsqn('w:hAnsi'), self.english_font)

    def _set_cell_font(self, cell, text: str, bold: bool = False):
        """为表格单元格设置字体"""
        for paragraph in cell.paragraphs:
            for run in paragraph.runs:
                self._set_font_for_run(run, text)
                if bold:
                    run.font.bold = True

    def _add_document_title(self, doc: Document, snapshot: ProjectSnapshot):
        """添加文档标题"""
        metadata = snapshot.metadata
        title = doc.add_heading(f"{metadata.name} - 参数表", 0)
        title.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 设置标题字体
        for run in title.runs:
            self._set_font_for_run(run, run.text)

        # 添加项目基本信息
        info_para = doc.add_paragraph()

        # 项目英文名
        name_run = info_para.add_run(f"项目英文名: {metadata.name_en}\n")
        name_run.bold = True
        self._set_font_for_run(name_run, name_run.text)

        # 导出时间
        export_time_str = (
            metadata.export_time.strftime('%Y-%m-%d %H:%M:%S')
            if metadata.export_time
            else datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        )
        time_run = info_para.add_run(f"导出时间: {export_time_str}\n")
        self._set_font_for_run(time_run, time_run.text)

        # 时间范围
        range_run = info_para.add_run(
            f"时间范围: {metadata.start_year} - {metadata.end_year} ({metadata.time_horizon}年)\n"
        )
        self._set_font_for_run(range_run, range_run.text)

        # 项目描述
        if metadata.description:
            desc_run = info_para.add_run(f"项目描述: {metadata.description}\n")
            self._set_font_for_run(desc_run, desc_run.text)

        # 添加分页符
        doc.add_page_break()

    def _add_single_value_table(self, doc: Document, snapshot: ProjectSnapshot):
        """添加单值参数表格"""
        # 检查是否有单值参数
        has_single_params = False
        for category in snapshot.categories:
            if any(not param.is_list for param in category.parameters):
                has_single_params = True
                break

        if not has_single_params:
            return

        # 添加表格标题
        heading = doc.add_heading("单值参数表", level=1)
        for run in heading.runs:
            self._set_font_for_run(run, run.text)

        # 创建表格
        table = doc.add_table(rows=1, cols=3)
        table.style = 'Table Grid'
        table.alignment = WD_TABLE_ALIGNMENT.CENTER

        # 设置表头
        header_cells = table.rows[0].cells
        headers = ["参数名称", "值", "单位"]
        for i, header in enumerate(headers):
            header_cells[i].text = header
            # 设置表头样式
            self._set_cell_font(header_cells[i], header, bold=True)
            for paragraph in header_cells[i].paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 添加数据行
        for category in snapshot.categories:
            # 检查该分类是否有单值参数
            has_single_params_in_cat = any(not param.is_list for param in category.parameters)
            if not has_single_params_in_cat:
                continue

            # 添加分类分隔行
            separator_row = table.add_row()
            separator_cell = separator_row.cells[0]
            separator_text = f"【{category.name} / {category.name_en}】"
            separator_cell.text = separator_text
            # 合并单元格
            separator_cell.merge(separator_row.cells[2])
            # 设置分隔行样式
            self._set_cell_font(separator_cell, separator_text, bold=True)
            for paragraph in separator_cell.paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

            # 添加该分类的单值参数
            for param in category.parameters:
                if param.is_list:
                    continue

                row = table.add_row()
                param_name = param.name or ""
                # 获取参数值（单值参数取第一个值）
                param_value = str(param.values[0].value) if param.values and param.values[0].value is not None else ""
                param_unit = param.unit or ""

                row.cells[0].text = param_name
                row.cells[1].text = param_value
                row.cells[2].text = param_unit

                # 设置字体
                self._set_cell_font(row.cells[0], param_name)
                self._set_cell_font(row.cells[1], param_value)
                self._set_cell_font(row.cells[2], param_unit)

        # 设置列宽
        table.columns[0].width = Inches(2.5)  # 参数名称
        table.columns[1].width = Inches(2.0)  # 值
        table.columns[2].width = Inches(1.0)  # 单位

        # 添加分页符
        doc.add_page_break()

    def _add_year_list_table(self, doc: Document, snapshot: ProjectSnapshot):
        """添加年份相关列表参数表格"""
        metadata = snapshot.metadata
        # 检查是否有年份相关列表参数
        has_year_list_params = False
        for category in snapshot.categories:
            if any(param.is_list and param.is_year_related for param in category.parameters):
                has_year_list_params = True
                break

        if not has_year_list_params:
            return

        # 添加表格标题
        heading = doc.add_heading("年份相关列表参数表", level=1)
        for run in heading.runs:
            self._set_font_for_run(run, run.text)

        # 生成年份列表（排除2025年）
        years = [
            metadata.start_year + i * metadata.year_step
            for i in range(metadata.time_horizon)
        ]
        years = [year for year in years if year != 2025]

        # 创建表格
        table = doc.add_table(rows=1, cols=len(years) + 2)
        table.style = 'Table Grid'
        table.alignment = WD_TABLE_ALIGNMENT.CENTER

        # 设置表头
        header_cells = table.rows[0].cells
        headers = ["参数名称"] + [str(year) for year in years] + ["单位"]
        for i, header in enumerate(headers):
            header_cells[i].text = header
            # 设置表头样式
            self._set_cell_font(header_cells[i], header, bold=True)
            for paragraph in header_cells[i].paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 添加数据行
        for category in snapshot.categories:
            # 检查该分类是否有年份相关列表参数
            has_year_list_params_in_cat = any(
                param.is_list and param.is_year_related for param in category.parameters
            )
            if not has_year_list_params_in_cat:
                continue

            # 添加分类分隔行
            separator_row = table.add_row()
            separator_cell = separator_row.cells[0]
            separator_text = f"【{category.name} / {category.name_en}】"
            separator_cell.text = separator_text
            # 合并单元格
            separator_cell.merge(separator_row.cells[len(years) + 1])
            # 设置分隔行样式
            self._set_cell_font(separator_cell, separator_text, bold=True)
            for paragraph in separator_cell.paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

            # 添加该分类的年份相关列表参数
            for param in category.parameters:
                if not (param.is_list and param.is_year_related):
                    continue

                row = table.add_row()
                param_name = param.name or ""

                row.cells[0].text = param_name

                # 添加年份值
                for i, year in enumerate(years):
                    val = param.values[i].value if i < len(param.values) else None
                    year_value = str(val) if val is not None and val != "" else ""
                    row.cells[1 + i].text = year_value
                    self._set_cell_font(row.cells[1 + i], year_value)

                param_unit = param.unit or ""
                row.cells[len(years) + 1].text = param_unit

                # 设置字体
                self._set_cell_font(row.cells[0], param_name)
                self._set_cell_font(row.cells[len(years) + 1], param_unit)

        # 设置列宽
        table.columns[0].width = Inches(3.0)  # 参数名称 - 增加宽度
        for i in range(len(years)):
            table.columns[1 + i].width = Inches(0.8)  # 年份列
        table.columns[len(years) + 1].width = Inches(1.0)  # 单位

        # 添加分页符
        doc.add_page_break()

    def _add_noyear_list_table(self, doc: Document, snapshot: ProjectSnapshot):
        """添加非年份列表参数表格"""
        # 检查是否有非年份列表参数
        has_noyear_list_params = False
        max_len = 0
        for category in snapshot.categories:
            for param in category.parameters:
                if param.is_list and not param.is_year_related:
                    has_noyear_list_params = True
                    max_len = max(max_len, param.list_length or len(param.values) or 0)

        if not has_noyear_list_params:
            return

        # 添加表格标题
        heading = doc.add_heading("非年份列表参数表", level=1)
        for run in heading.runs:
            self._set_font_for_run(run, run.text)

        # 创建表格
        table = doc.add_table(rows=1, cols=max_len + 2)
        table.style = 'Table Grid'
        table.alignment = WD_TABLE_ALIGNMENT.CENTER

        # 设置表头
        header_cells = table.rows[0].cells
        headers = ["参数名称"] + [str(i) for i in range(1, max_len + 1)] + ["单位"]
        for i, header in enumerate(headers):
            header_cells[i].text = header
            # 设置表头样式
            self._set_cell_font(header_cells[i], header, bold=True)
            for paragraph in header_cells[i].paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

        # 添加数据行
        for category in snapshot.categories:
            # 检查该分类是否有非年份列表参数
            has_noyear_list_params_in_cat = any(
                param.is_list and not param.is_year_related for param in category.parameters
            )
            if not has_noyear_list_params_in_cat:
                continue

            # 添加分类分隔行
            separator_row = table.add_row()
            separator_cell = separator_row.cells[0]
            separator_text = f"【{category.name} / {category.name_en}】"
            separator_cell.text = separator_text
            # 合并单元格
            separator_cell.merge(separator_row.cells[max_len + 1])
            # 设置分隔行样式
            self._set_cell_font(separator_cell, separator_text, bold=True)
            for paragraph in separator_cell.paragraphs:
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

            # 添加该分类的非年份列表参数
            for param in category.parameters:
                if not (param.is_list and not param.is_year_related):
                    continue

                row = table.add_row()
                param_name = param.name or ""

                row.cells[0].text = param_name

                # 添加列表值
                for i in range(max_len):
                    val = param.values[i].value if i < len(param.values) else None
                    list_value = str(val) if val is not None and val != "" else ""
                    row.cells[1 + i].text = list_value
                    self._set_cell_font(row.cells[1 + i], list_value)

                param_unit = param.unit or ""
                row.cells[max_len + 1].text = param_unit

                # 设置字体
                self._set_cell_font(row.cells[0], param_name)
                self._set_cell_font(row.cells[max_len + 1], param_unit)

        # 设置列宽
        table.columns[0].width = Inches(2.5)  # 参数名称
        for i in range(max_len):
            table.columns[1 + i].width = Inches(0.8)  # 列表值列
        table.columns[max_len + 1].width = Inches(1.0)  # 单位

